package com.example.design_pattern.decorator;

// 本例演示的是：装饰器模式。

// 定义形状接口
interface Shape {
    void draw();
}

// 具体形状：圆形
class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Draw a circle.");
    }
}



// 抽象装饰器类
abstract class ShapeDecorator implements Shape {
    protected Shape decoratedShape;

    // 构造函数
    public ShapeDecorator(Shape decoratedShape) {
        // 给自己的某些属性赋值。
        this.decoratedShape = decoratedShape;
    }

    public void draw() {
        decoratedShape.draw();
    }
}

// 具体装饰器类：添加颜色
class ColorDecorator extends ShapeDecorator {
    // 保存颜色的
    private String color;

    // 构造函数
    // 这个Shape decoratedShap 到时候传实际传进来的是circle。decoratedShape这种带ed的命名，此处表被动，也就是被装饰的对象。这个ed不是表示已经装饰过了的对象哦。
    public ColorDecorator(Shape decoratedShape, String color) {
        // 这个具体装饰器类，懒得自己再写一次自己父类，也就是ShapeDecorator的构造方法里面的this.decoratedShape = decoratedShape;这句话，直接super()就可以调用父类的构造方法。
        super(decoratedShape);
        // 在父类的构造方法基础上，自己在添加一些逻辑。
        this.color = color;
    }

    @Override
    public void draw() {
        // 这个是原来就有的方法。这其实也不用啥反射之类的。因为人家给你把被装饰对象都传进来你这个装饰处理类了，你直接用被装饰对象点出目标方法调用就好了。
        decoratedShape.draw();
        // 这个是增强的部分。这是我们本案例的中心。那就是，增强circle实例对象的draw方法。
        System.out.println("Fill with " + color + " color.");
    }
}



public class DecoratorTest {
    public static void main(String[] args) {
        // 创建一个圆形
        Shape circle = new Circle();

        // 创建一个带有颜色装饰器的圆形。就把circle对象交给装饰公司五装饰了。
        // 这里new的时候，就是底层执行的ColorDecorator的构造方法。这个时候返回的类，其实访问的就是一个装饰器类的实例对象，这个装饰器类里面自己也定义了draw方法。
        Shape coloredCircle = new ColorDecorator(circle, "red");

        // 绘制圆形
        circle.draw();

        // 绘制带有颜色装饰器的圆形
        coloredCircle.draw();
    }
}

